﻿using System;
using System.Collections.Generic;
using Adalbertus.BudgetPlanner.Domain;
using Adalbertus.BudgetPlanner.Domain.Repositories;

namespace Adalbertus.BudgetPlanner.Services
{
    public class BudgetService : BaseService<Budget>, IBudgetService
    {
        public BudgetService(IRepositoryFactory repositoryFactory, IUnitOfWorkProvider unitOfWorkProvider)
            : base(repositoryFactory, unitOfWorkProvider)
        {
        }

        public Budget GenerateEmptyBudgetForNextMonth(DateTime contextDate)
        {
            using (IUnitOfWork unitOfWork = UnitOfWorkProvider.OpenUnitOfWork())
            {
                IRepository<CashFlow> cashFlowRepository = RepositoryFactory.CreateRepository<CashFlow>(unitOfWork);
                IRepository<Budget> budgetRepository = RepositoryFactory.CreateRepository<Budget>(unitOfWork);

                IEnumerable<CashFlow> cashFlows = cashFlowRepository.GetAll();
                Budget budget = Budget.CreateEmptyForNextMonth(contextDate, cashFlows);

                budgetRepository.Save(budget);

                unitOfWork.Commit();
                return budget;
            }
        }

        public Budget GetBudgetByDate(DateTime budgetDate)
        {
            using (IUnitOfWork unitOfWork = UnitOfWorkProvider.OpenUnitOfWork())
            {
                IBudgetRepository budgetRepository = RepositoryFactory.CreateBudgetRepository(unitOfWork);
                Budget budget = budgetRepository.GetBudgetByDate(budgetDate);
                return budget;
            }
        }

        public Budget GetDraftedBudget()
        {
            using (IUnitOfWork unitOfWork = UnitOfWorkProvider.OpenUnitOfWork())
            {
                IBudgetRepository budgetRepository = RepositoryFactory.CreateBudgetRepository(unitOfWork);
                var incomesRepository = RepositoryFactory.CreateRepository<IncomeEntry>(unitOfWork);

                Budget budget = budgetRepository.GetDraftedBudget();
                
                return budget;
            }
        }

        public override void Save(Budget budget)
        {
            using (IUnitOfWork unitOfWork = UnitOfWorkProvider.OpenUnitOfWork())
            {
                IRepository<IncomeEntry> incomeEntryRepository = RepositoryFactory.CreateRepository<IncomeEntry>(unitOfWork);
                IRepository<SavingEntry> savingEntryRepository = RepositoryFactory.CreateRepository<SavingEntry>(unitOfWork);
                IRepository<Budget> budgetRepository = RepositoryFactory.CreateRepository<Budget>(unitOfWork);

                incomeEntryRepository.Save(budget.Incomes);
                savingEntryRepository.Save(budget.Savings);
                budgetRepository.Save(budget);

                unitOfWork.Commit();
            }
        }
    }
}
